//
//  UIGradientLabel.swift
//  GradientLabel-Swift
//
//  Created by 万孟超 on 2022/1/19.
//

import UIKit

class UIGradientLabel: UILabel {
    private var link : CADisplayLink? = nil
    private var colors : [Any] {
        get {
            guard let gradientColors = gradientColor else{
                return [self.textColor.cgColor,self.textColor.cgColor]
            }
            var color : [Any] = []
            for c in gradientColors {
                color.append(c.cgColor)
            }
            return color
        }
    }
    var gradientColor : [UIColor]?

    func startTextGradient() {
        link = CADisplayLink.init(target: self, selector: #selector(changeState))
        if #available(iOS 10.0, *) {
            link?.preferredFramesPerSecond = 60;
        }else{
            link?.frameInterval = 1
        }
        link?.add(to: RunLoop.current, forMode: .common)
    }
    
    @objc private func changeState() {
        self.setNeedsDisplay()
    }
    
    override func draw(_ rect: CGRect) {
        struct ConsoleBox {
            static var adding : CGFloat = 0
            static var add : Bool = true
        }
        let context = UIGraphicsGetCurrentContext()
        let style : NSMutableParagraphStyle = NSMutableParagraphStyle.init()
        style.alignment = self.textAlignment
        var attribute : [NSAttributedString.Key : Any]? = [:]
        attribute?.updateValue(style, forKey: .paragraphStyle)
        attribute?.updateValue(self.font as Any, forKey:.font)
        self.text?.draw(with: rect, options: .usesLineFragmentOrigin, attributes: attribute, context: nil)
        context?.translateBy(x: 0.0, y: rect.size.height);
        context?.scaleBy(x: 1.0, y: -1.0);
        let alphaMsk : CGImage? = context?.makeImage()
        context?.clear(rect)
        context?.clip(to: rect, mask: alphaMsk!)
        
        let colorSpace : CGColorSpace? = CGColorSpaceCreateDeviceRGB()
        let gradient = CGGradient.init(colorsSpace: colorSpace, colors: colors as CFArray, locations: nil)
        var startPoint = CGPoint.init(x: -rect.size.width, y: 0)
        var endPoint = CGPoint.init(x: 0, y: rect.size.height)
        
        if ConsoleBox.adding > rect.size.width * 2 {
            ConsoleBox.add = false
        }else if ConsoleBox.adding <= 0 {
            ConsoleBox.add = true
        }
        if ConsoleBox.add {
            ConsoleBox.adding += rect.size.width / 150
        }else{
            ConsoleBox.adding -= rect.self.width / 150
        }
        startPoint = CGPoint.init(x: startPoint.x + ConsoleBox.adding, y: startPoint.y)
        endPoint = CGPoint.init(x: endPoint.x + ConsoleBox.adding, y: endPoint.y)
        
        context?.drawLinearGradient(gradient!, start: startPoint, end: endPoint, options: [.drawsBeforeStartLocation,.drawsAfterEndLocation])
    }

}
